{#
  Template for 'request_utilities.cc'.
  This file contains implementation of request-related methods contained in 'message_utilities.h'.
#}

#include <algorithm>

#include "contrib/kafka/filters/network/test/message_utilities.h"

#include "contrib/kafka/filters/network/source/external/requests.h"

namespace Envoy {
namespace Extensions {
namespace NetworkFilters {
namespace Kafka {

std::vector<int16_t> MessageUtilities::apiKeys() {
  std::vector<int16_t> result;
  {% for message_type in message_types %}
  result.push_back({{ message_type.get_extra('api_key') }});
  {% endfor %}
  return result;
}

int16_t MessageUtilities::requestApiVersions(const int16_t api_key) {
  switch (api_key) {
  {% for message_type in message_types %}
  case {{ message_type.get_extra('api_key') }} :
    return {{ message_type.compute_field_lists() | length }} ;
  {% endfor %}
  default:
    throw EnvoyException("unsupported api key used in test code");
  }
}

std::vector<AbstractRequestSharedPtr> MessageUtilities::makeRequests(
  const int16_t api_key, int32_t& correlation_id) {

  const std::vector<int16_t> api_keys = apiKeys();
  if (std::find(api_keys.begin(), api_keys.end(), api_key) == api_keys.end()) {
    throw EnvoyException("unsupported api key used in test code");
  }

  std::vector<AbstractRequestSharedPtr> result;
  {% for message_type in message_types %}
  if ({{ message_type.get_extra('api_key') }} == api_key) {
    {% for field_list in message_type.compute_field_lists() %}
    {
      const RequestHeader header = {
          {{ message_type.get_extra('api_key') }}, {{ field_list.version }}, correlation_id++,
          "id" };
      const {{ message_type.name }} data = { {{ field_list.example_value() }} };
      const AbstractRequestSharedPtr request = std::make_shared<Request<{{ message_type.name }}>>(
          header, data);
      result.push_back(request);
    }
    {% endfor %}
  }
  {% endfor %}
  return result;
}

std::vector<AbstractRequestSharedPtr> MessageUtilities::makeAllRequests() {
  std::vector<AbstractRequestSharedPtr> result;
  int32_t correlation_id = 0;
  for (const int16_t i : MessageUtilities::apiKeys()) {
    const std::vector<AbstractRequestSharedPtr> tmp =
        MessageUtilities::makeRequests(i, correlation_id);
    result.insert(result.end(), tmp.begin(), tmp.end());
  }
  return result;
}

std::string MessageUtilities::requestMetric(const int16_t api_key) {
  switch (api_key) {
  {% for message_type in message_types %}
  case {{ message_type.get_extra('api_key') }} :
    return "kafka.prefix.request.{{ message_type.name_in_c_case() }}" ;
  {% endfor %}
  default:
    throw EnvoyException("unsupported api key used in test code");
  }
}

} // namespace Kafka
} // namespace NetworkFilters
} // namespace Extensions
} // namespace Envoy
